<template>
  <scroll-view
    :id="scrollId"
    class="tn-virtual-list__scroll-view"
    :style="scrollViewStyle"
    scroll-y
    @scroll="handleScrollEvent"
  >
    <!-- 总数据容器 -->
    <view class="data__container" :style="{height: `${itemTotalHeight}px`}">
      <!-- 数据内容 -->
      <view class="data__content" :style="{transform: `translateY(${scrollTop}px)`}">
        <view class="list__container">
          <view
            v-for="(item, index) in visibleData"
            :key="item['unique_index']"
            :id="`virtual_cell-${item['tn_index']}`"
            class="list__cell"
          >
             <slot :item="item" :index="index" :tn_index="item['tn_index']"></slot>
          </view>
        </view>
       
      </view>
    </view>
  </scroll-view>
</template>

<script lang="ts" setup>
import {
  ref,
  ComponentInternalInstance,
  computed,
  CSSProperties,
  getCurrentInstance, 
onMounted,
nextTick
} from 'vue'
import { virtualListProps } from '../../../types/tn-virtual-list'
import { uuid, getRectInfo, handleValueWithUnit } from '../../../utils'

const props = defineProps(virtualListProps)

const instance = getCurrentInstance() as ComponentInternalInstance
const scrollId = uuid()

// 列表数据
const realListData = computed<any[]>(() => {
  return props.data.map((item, index) => {
    return {
      ...item,
      'tn_index': index,
      'unique_index': uuid()
    }
  })
})

// scrollView样式
const scrollViewStyle = computed<CSSProperties>(() => {
  let style: CSSProperties = {}
  // 设置宽高
  if (props?.height) style.height = handleValueWithUnit(props.height)
  if (props?.width) style.width = handleValueWithUnit(props.width)
  return style
})

// item的数量
const itemLength = computed<number>(() => {
  if (!props?.data) return 0
  return props.data.length
})
// item的总高度
const itemTotalHeight = computed<number>(() => {
  return itemHeight.value * itemLength.value
})

let containerHeight = ref<number>(0)
let containerTop: number = 0
// 初始化可视化scroll容器
let initCount: number = 0
const initScrollContainer = async () => {
  const rectInfo = await getRectInfo(`#${scrollId}`, instance)
  if (!rectInfo) {
    if (initCount > 10) {
      return console.error('[tn-virtual-list]初始化虚拟列表节点信息失败')
    }
    setTimeout(() => {
      initScrollContainer()
      initCount++
    }, 50)
    return
  }

  initCount = 0
  containerTop = rectInfo?.top || 0
  containerHeight.value = rectInfo?.height || 0

  // 初始化显示的数据
  _updateIndex(0)
  initItemRect()
}
// 获取item容器的高度
let itemHeight = ref<number>(0)
const initItemRect = async () => {
  const itemRectInfo = await getRectInfo(`#virtual_cell-0`, instance)
  if (!itemRectInfo) {
    if (initCount > 10) {
      return console.error('[tn-virtual-list]初始化虚拟列表Item节点信息失败')
    }
    setTimeout(() => {
      initItemRect()
      initCount++
    }, 50)
    return
  }

  initCount = 0
  // console.log(itemRectInfo);
  itemHeight.value = itemRectInfo?.height || 0
  _updateIndex(0)
}

// 每屏显示的数据数量
const visibleCount = computed<number>(() => {
    return Math.round(containerHeight.value / itemHeight.value)
})
const preloadPage = computed<number>(() => {
  if (props?.preloadPage !== undefined) {
    return Number(props.preloadPage)
  }
  return 3
})
// 展示的数据信息
let start = ref<number>(0)
let end = ref<number>(0)
let lastStart: number = 0
let lastEnd: number = 0
const visibleData = ref<any[]>([])

let scrollTop = ref<number>(0)
// 滚动事件
const virtualScrollDetectTime = computed<number>(() => {
  return 1000 / (Number(props?.scrollGatherFreq) || 60)
})
let lastScrollTimeStamp: number = 0
const handleScrollEvent = (e: any) => {
  const _scrollTop: number = e?.detail?.scrollTop || 0
  let currentScrollTimeStamp: number = (new Date()).getTime()
  if (_scrollTop !== 0 && lastScrollTimeStamp && currentScrollTimeStamp - lastScrollTimeStamp <= virtualScrollDetectTime.value) {
    return
  }
  lastScrollTimeStamp = currentScrollTimeStamp


  const scrollIndex = Math.floor(_scrollTop / itemHeight.value)
  console.log(_scrollTop, scrollIndex);
  _updateIndex(scrollIndex)
}

// 更新开始/结束Index
const _updateIndex = (scrollIndex: number) => {
  let _start: number = itemHeight.value === 0 ? 0 : scrollIndex - visibleCount.value * preloadPage.value
  let _end: number = itemHeight.value === 0 ? 1 : scrollIndex + visibleCount.value * preloadPage.value
  if (itemHeight.value !== 0 && (_start === lastStart || _end === lastEnd)) {
    return
  }

  start.value = Math.max(0, _start)
  end.value = Math.min(_end, itemLength.value)
  // #ifdef MP-WEIXIN
  scrollTop.value = start.value * itemHeight.value

  lastStart = start.value
  lastEnd = end.value

  const _realListData: any[] = JSON.parse(JSON.stringify(realListData.value))
  visibleData.value = _realListData.slice(start.value, end.value + 1)
  // console.log(scrollIndex, start.value, end.value, scrollTop.value, visibleCount.value);
}

onMounted(() => {
  nextTick(() => {
    setTimeout(() => {
      initScrollContainer()
    }, 50);
  })
})
</script>

<script lang="ts">
export default {
  options: {
    // 在微信小程序中将组件节点渲染为虚拟节点，更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
    virtualHost: true
  }
}
</script>

<style lang="scss" scoped>

.tn-virtual-list {
  &__scroll-view {
    position: relative;
    width: 100%;
    height: 100%;

    .data {
      &__container {
        width: 100%;
        position: relative;
      }
      &__content {
        position: absolute;
        width: 100%;
        top: 0;
        left: 0;
      }
    }
  }
}
</style>
